package com.nereyda.application.managers
{
	import com.nereyda.application.loaders.GadgetLoader;
	import com.nereyda.application.locators.*;
	import com.nereyda.view.MainMenu;
	
	import flash.events.Event;
	
	import mx.core.UIComponent;
	import mx.managers.PopUpManager;
	
	/**
	 * Controlador de miniaplicaciones. Gestiona la carga, descarga
	 * y opciones de los gadgets. Definido como singleton para ofrecer
	 * acceso global a los gadgets cargados.
	 */
	public class GadgetManager
	{
		private var gadgetList :Array = [];
		
		/**
		 * Agrega una nueva instancia de un gadget.
		 * 
		 * @param gadgetLoader Instance de la miniaplicación que se agregará.
		 */
		public function addGadget( gadgetLoader:GadgetLoader ):void
		{
			gadgetList.push( gadgetLoader );
		}
		
		/**
		 * Agrega un nuevo gadget, y muestra el ícono asociado
		 * en el menú principal de la aplicación.
		 * 
		 * @param gadgetLoader     Instance de la miniaplicación que se agregará.
		 * @param tooltipText      Ayuda contextual del elemento en el menú.
		 * @param itemClickHandler Función que se ejecutará al producirse el evento click en el item del menú.
		 */
		public function addGadgetMenu( gadgetLoader:Class, tooltipText:String = null, itemClickHandler:Function = null ):void
		{
			var mainMenu   :MainMenu = AppLocator.getInstance().mainMenu;
			var gadgetInst :GadgetLoader = new gadgetLoader();
			
			// Agrega el ícono del gadget al menú, y guarda 
			// la referencia al objeto Image.
			//
			gadgetInst.displayIcon = mainMenu.addCommand(
				tooltipText || gadgetInst.getGadgetName(),
				gadgetInst.getGadgetName(),
				itemClickHandler || this.menuItemClickHandler 
			);
			
			this.addGadget( gadgetInst );
		}
		
		/**
		 * Muestra una miniaplicación en el escritorio,
		 * a partir de su nombre.
		 * 
		 * @param gadgetName Nombre del gadget.
		 * @param modal      Especifica si se mostrará de forma modal.
		 */
		public function showGadgetByName( gadgetName:String, modal:Boolean = false ):void
		{
			for each( var loader:GadgetLoader in gadgetList )
			{
				if ( loader.getGadgetName() == gadgetName ) {
					this.showGadget( loader, modal );
					
					return;
				}
			}
		}
		
		/**
		 * Muestra la miniaplicación especificada en el escritorio.
		 * 
		 * @param gadgetLoader Gadget que se mostrará.
		 * @param modal        Especifica si se mostrará de forma modal.
		 */
		public function showGadget( gadgetLoader:GadgetLoader, modal:Boolean = false ):void
		{
			if ( gadgetLoader.loaded ) 
			{
				this.bringToFront( gadgetLoader );

				return;
			}

			PopUpManager.addPopUp(
				UIComponent( gadgetLoader ),
				AppLocator.getInstance().desktop,
				modal
			);

			PopUpManager.centerPopUp( UIComponent( gadgetLoader ) );
		}
		
		/**
		 * Descarga una miniaplicación cargada previamente.
		 * 
		 * @param loader Miniaplicación que se descargará.
		 */
		public function unloadGadget( loader:GadgetLoader ):void
		{
			if ( !loader.instance ) {
				return;
			}
			
			PopUpManager.removePopUp( loader.instance );
			
			loader.loaded = false;			
		}
		
		public function unloadAll():void
		{
			for each( var loader:GadgetLoader in gadgetList )
			{
				this.unloadGadget( loader );
			}
		}

		public function bringToFront( gadget:GadgetLoader ):void
		{
			gadget.instance.visible = true;
			
			PopUpManager.addPopUp( UIComponent(gadget), AppLocator.getInstance().desktop );
			PopUpManager.centerPopUp( UIComponent(gadget) );
			PopUpManager.bringToFront( gadget.instance );
		}
		
		public function notifyGadgetLoad( gadget:GadgetLoader ):void
		{
			for each( var loader:GadgetLoader in gadgetList )
			{
				if ( loader.getGadgetName() == gadget.getGadgetName() ) 
				{
					gadget.loaded = true;
					gadget.instance = UIComponent(gadget);
					
					break;
				}
			}
		}
		
		private function menuItemClickHandler( event:Event ):void
		{
			this.showGadgetByName( event.currentTarget.id );
		}
		
		// Devuelve una instancia única de la clase.
		//
		private static var instance :GadgetManager = null;
		
		public static function getInstance():GadgetManager
		{
			if ( instance == null )
				instance = new GadgetManager();
			
			return( instance );
		}
	}
}